From fe2b56bbc169f4293b62caa3240231575ba267bc Mon Sep 17 00:00:00 2001 From: robertl Date: Fri, 2 Sep 2005 23:49:18 +0000 Subject: [PATCH] Olaf adds support for Suunto Track Manager (STM) WaypointPlus format. --- gpsbabel/Makefile | 3 +- gpsbabel/README | 13 + gpsbabel/reference/route/stmwpp-route.gpx | 102 ++++++++ gpsbabel/reference/route/stmwpp-route.txt | 10 + gpsbabel/reference/track/stmwpp-track.gpx | 172 +++++++++++++ gpsbabel/reference/track/stmwpp-track.txt | 54 ++++ gpsbabel/stmwpp.c | 295 ++++++++++++++++++++++ gpsbabel/testo | 11 + gpsbabel/vecs.c | 9 +- 9 files changed, 667 insertions(+), 2 deletions(-) create mode 100644 gpsbabel/reference/route/stmwpp-route.gpx create mode 100644 gpsbabel/reference/route/stmwpp-route.txt create mode 100644 gpsbabel/reference/track/stmwpp-track.gpx create mode 100644 gpsbabel/reference/track/stmwpp-track.txt create mode 100644 gpsbabel/stmwpp.c diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index d631496e3..52727d918 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -39,7 +39,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \ igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \ vcf.o overlay.o kml.o google.o lowranceusr.o an1.o tomtom.o \ tef_xml.o maggeo.o pathaway.o vitosmt.o gdb.o bcr.o coto.o \ - ignrando.o + ignrando.o stmwpp.o FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o trackfilter.o discard.o @@ -244,6 +244,7 @@ smplrout.o: smplrout.c defs.h queue.h gbtypes.h grtcirc.h sort.o: sort.c defs.h queue.h gbtypes.h stackfilter.o: stackfilter.c defs.h queue.h gbtypes.h strptime.o: strptime.c strptime.h +stmwpp.o: stmwpp.c defs.h queue.h gbtypes.h csv_util.h tef_xml.o: tef_xml.c defs.h queue.h gbtypes.h xmlgeneric.h text.o: text.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \ jeeps/../defs.h jeeps/gpsport.h jeeps/gpsserial.h jeeps/gpssend.h \ diff --git a/gpsbabel/README b/gpsbabel/README index dc334484e..5c49caafb 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -1037,7 +1037,20 @@ THE FORMATS index - Use track number from input data for output. The range is 1 to number of tracks in input. + + STMwpp + + Support for Suunto Track Manager (STM) WaypointPlus format.. + Simple structure with coordinates and timestamp. Route points + (waypoints) have additionaly shortname. + The files can only contain one route or one track. + http://www.suunto.fi + + Options: + + index - Use route/track number from input data for output. + DATA FILTERS GPSBabel supports data filtering. Data filters are invoked from diff --git a/gpsbabel/reference/route/stmwpp-route.gpx b/gpsbabel/reference/route/stmwpp-route.gpx new file mode 100644 index 000000000..c3690762d --- /dev/null +++ b/gpsbabel/reference/route/stmwpp-route.gpx @@ -0,0 +1,102 @@ + + + + + + + NARVA + NARVA + NARVA + + + + Liebknechtstras + Liebknechtstras + Liebknechtstras + + + + Jahnstrasse11 + Jahnstrasse11 + Jahnstrasse11 + + + + Elsterberg + Elsterberg + Elsterberg + + + + Greiz + Greiz + Greiz + + + + Gosel + Gosel + Gosel + + + + 3 + 3 + 3 + + + + Altenburg-Umgehung + Altenburg-Umgehung + Altenburg-Umgehung + + + + Völkerschlachtdenkmal + Völkerschlachtdenkmal + Völkerschlachtdenkmal + + + + + NARVA + + + + Liebknechtstras + + + + Jahnstrasse11 + + + + Elsterberg + + + + Greiz + + + + Gosel + + + + 3 + + + + Altenburg-Umgehung + + + + Völkerschlachtdenkmal + + + diff --git a/gpsbabel/reference/route/stmwpp-route.txt b/gpsbabel/reference/route/stmwpp-route.txt new file mode 100644 index 000000000..66a200c9c --- /dev/null +++ b/gpsbabel/reference/route/stmwpp-route.txt @@ -0,0 +1,10 @@ +Datum,WGS 84,WGS 84,0,0,0,0,0 +WP,D,NARVA,50.4926189,12.1054487,09/03/2005,00:00:00.90, +WP,D,Liebknechtstras,50.4938369,12.106101,09/03/2005,00:00:00.90, +WP,D,Jahnstrasse11,50.4936628,12.1071524,09/03/2005,00:00:00.90, +WP,D,Elsterberg,50.6107952,12.1738022,09/03/2005,00:00:00.90, +WP,D,Greiz,50.654763,12.2049567,09/03/2005,00:00:00.90, +WP,D,Gosel,50.8441256,12.4087572,09/03/2005,00:00:00.90, +WP,D,3,50.8773405,12.4338887,09/03/2005,00:00:00.90, +WP,D,Altenburg-Umgehung,50.9649551,12.4359193,09/03/2005,00:00:00.90, +WP,D,Völkerschlachtdenkmal,51.3145207,12.4091433,09/03/2005,00:00:00.90, diff --git a/gpsbabel/reference/track/stmwpp-track.gpx b/gpsbabel/reference/track/stmwpp-track.gpx new file mode 100644 index 000000000..ba8b2e0b2 --- /dev/null +++ b/gpsbabel/reference/track/stmwpp-track.gpx @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gpsbabel/reference/track/stmwpp-track.txt b/gpsbabel/reference/track/stmwpp-track.txt new file mode 100644 index 000000000..fda1fa51d --- /dev/null +++ b/gpsbabel/reference/track/stmwpp-track.txt @@ -0,0 +1,54 @@ +Datum,WGS 84,WGS 84,0,0,0,0,0 +TP,D,45.187113,4.6607297,08/23/2005,15:25:12.812, +TP,D,45.1868455,4.660163,08/23/2005,15:25:22.822, +TP,D,45.1863955,4.6599324,08/23/2005,15:25:39.839, +TP,D,45.1859246,4.6598826,08/23/2005,15:25:58.858, +TP,D,45.185478,4.6597676,08/23/2005,15:26:16.816, +TP,D,45.1850178,4.6597388,08/23/2005,15:26:33.833, +TP,D,45.1845797,4.6596044,08/23/2005,15:26:53.853, +TP,D,45.1841254,4.6596267,08/23/2005,15:27:09.89, +TP,D,45.1836672,4.6595521,08/23/2005,15:27:28.828, +TP,D,45.1836814,4.6588984,08/23/2005,15:28:02.82, +TP,D,45.183994,4.6584016,08/23/2005,15:28:15.815, +TP,D,45.1846076,4.657295,08/23/2005,15:28:30.830, +TP,D,45.1850065,4.6558776,08/23/2005,15:28:44.844, +TP,D,45.1845094,4.6552681,08/23/2005,15:28:54.854, +TP,D,45.1839276,4.6546767,08/23/2005,15:29:04.84, +TP,D,45.1834919,4.6543834,08/23/2005,15:29:16.816, +TP,D,45.1835007,4.6537414,08/23/2005,15:29:26.826, +TP,D,45.1833348,4.6531515,08/23/2005,15:29:42.842, +TP,D,45.1830662,4.6526252,08/23/2005,15:29:59.859, +TP,D,45.1830017,4.6519839,08/23/2005,15:30:15.815, +TP,D,45.1829897,4.6513269,08/23/2005,15:30:32.832, +TP,D,45.1829101,4.6506828,08/23/2005,15:30:44.844, +TP,D,45.1825391,4.6502882,08/23/2005,15:30:56.856, +TP,D,45.1821259,4.6499932,08/23/2005,15:31:14.814, +TP,D,45.1817943,4.6495713,08/23/2005,15:31:31.831, +TP,D,45.1816251,4.6489743,08/23/2005,15:31:50.850, +TP,D,45.1815118,4.6483493,08/23/2005,15:32:13.813, +TP,D,45.1812957,4.647775,08/23/2005,15:32:34.834, +TP,D,45.181057,4.6472012,08/23/2005,15:32:56.856, +TP,D,45.1807201,4.6467576,08/23/2005,15:33:15.815, +TP,D,45.1804336,4.6462213,08/23/2005,15:33:32.832, +TP,D,45.180078,4.6458228,08/23/2005,15:33:51.851, +TP,D,45.1796982,4.6454427,08/23/2005,15:34:09.89, +TP,D,45.1793545,4.6450331,08/23/2005,15:34:29.829, +TP,D,45.1788317,4.644899,08/23/2005,15:34:50.850, +TP,D,45.1788737,4.6442499,08/23/2005,15:35:15.815, +TP,D,45.1791315,4.6437253,08/23/2005,15:35:33.833, +TP,D,45.17924,4.6431102,08/23/2005,15:35:55.855, +TP,D,45.179606,4.6427364,08/23/2005,15:36:16.816, +TP,D,45.1797593,4.6421412,08/23/2005,15:36:39.839, +TP,D,45.1798951,4.6415263,08/23/2005,15:37:03.83, +TP,D,45.1799366,4.6408842,08/23/2005,15:37:33.833, +TP,D,45.1796929,4.6403555,08/23/2005,15:38:06.86, +TP,D,45.1797172,4.6397143,08/23/2005,15:38:36.836, +TP,D,45.1795321,4.6391257,08/23/2005,15:39:06.86, +TP,D,45.179173,4.6387332,08/23/2005,15:39:29.829, +TP,D,45.1790175,4.6381358,08/23/2005,15:39:51.851, +TP,D,45.1788947,4.6375252,08/23/2005,15:40:14.814, +TP,D,45.1786746,4.6369489,08/23/2005,15:40:34.834, +TP,D,45.1783918,4.6364349,08/23/2005,15:40:47.847, +TP,D,45.1781717,4.6358662,08/23/2005,15:40:59.859, +TP,D,45.1778664,4.6351585,08/23/2005,15:41:09.89, +TP,D,45.1774999,4.6345872,08/23/2005,15:41:19.819, diff --git a/gpsbabel/stmwpp.c b/gpsbabel/stmwpp.c new file mode 100644 index 000000000..4c3f94fac --- /dev/null +++ b/gpsbabel/stmwpp.c @@ -0,0 +1,295 @@ + /* + + Support for "Suunto Track Manager" (STM) WaypointPlus files, + see homepage "http://www.suunto.fi" for more details, + + Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA +*/ + +#include "defs.h" +#include "csv_util.h" +#include +#include +#include + +static FILE *fin; +static FILE *fout; +static route_head *track, *route; +static waypoint *wpt; + +#define MYNAME "STMwpp" + +#define STM_NOTHING 0 +#define STM_WAYPT 1 +#define STM_TRKPT 2 + +static int track_index; +static int track_num; +static int what; + +static char *index_opt = NULL; + +static +arglist_t stmwpp_args[] = +{ + {"index", &index_opt, "Index of route/track to write (if more the one in source)", NULL, ARGTYPE_INT }, + {0, 0, 0, 0, 0} +}; + + +static void +stmwpp_rd_init(const char *fname) +{ + fin = xfopen(fname, "r", MYNAME); + track = NULL; + route = NULL; + wpt = NULL; +} + +static void +stmwpp_rd_deinit(void) +{ + fclose(fin); +} + +static void +stmwpp_data_read(void) +{ + char buff[1024]; + char *c; + + what = STM_NOTHING; + fgets(buff, sizeof(buff), fin); + + if (strncmp(buff, "Datum,WGS 84,WGS 84,", 20) != 0) + fatal(MYNAME ": Invalid GPS datum or not \"WaypointPlus\"\" file!\n"); + + while (fgets(buff, sizeof(buff), fin) != NULL) + { + char *c; + int column = -1; + struct tm time; + + wpt = NULL; + memset(&time, 0, sizeof(time)); + + c = csv_lineparse(buff, ",", "", column++); + while (c != NULL) + { + int new_what; + + switch(column) + { + case 0: + if (case_ignore_strcmp(c, "WP") == 0) + { + new_what = STM_WAYPT; + } + else if (case_ignore_strcmp(c, "TP") == 0) + { + new_what = STM_TRKPT; + } + else + fatal(MYNAME ": Unknown feature \"%s\"!\n", c); + + if ((what != STM_NOTHING) && (new_what != what)) + fatal(MYNAME ": Only one feature (route or track) is supported by STM!\n"); + + what = new_what; + wpt = waypt_new(); + break; + + case 1: + if (what == STM_TRKPT) column++; /* no name -> skip column two */ + break; + + case 2: + wpt->shortname = xstrdup(c); + break; + + case 3: + wpt->latitude = atof(c); + break; + + case 4: + wpt->longitude = atof(c); + break; + + case 5: + sscanf(c, "%d/%d/%d", &time.tm_mon, &time.tm_mday, &time.tm_year); + break; + + case 6: + sscanf(c, "%d:%d:%d.%d", &time.tm_hour, &time.tm_min, &time.tm_sec, &wpt->centiseconds); + if (what == STM_TRKPT) + wpt->centiseconds /= 10; + break; + + default: + break; + } + c = csv_lineparse(NULL, ",", "", column++); + } + if (wpt != NULL) + { + time.tm_year -= 1900; + time.tm_mon--; + wpt->creation_time = mkgmtime(&time); + + switch(what) + { + case STM_WAYPT: + waypt_add(waypt_dupe(wpt)); + if (route == NULL) + { + route = route_head_alloc(); + route_add_head(route); + } + route_add_wpt(route, wpt); + break; + + case STM_TRKPT: + if (track == NULL) + { + track = route_head_alloc(); + track_add_head(track); + } + route_add_wpt(track, wpt); + break; + } + wpt = NULL; + } + } +} + +static void +stmwpp_rw_init(const char *fname) +{ + fout = xfopen(fname, "w", MYNAME); +} + +static void +stmwpp_rw_deinit(void) +{ + fclose(fout); +} + +static void +stmwpp_track_hdr(const route_head *track) +{ + track_num++; +} + +static void +stmwpp_track_tlr(const route_head *track) +{ +} + +static void +stmwpp_write_double(const double val) +{ + char buff[64]; + char *c; + + c = buff + snprintf(buff, sizeof(buff), "%3.7f", val); + while (*--c == '0') *c = '\0'; + if (*c == '.') *c = '0'; + fprintf(fout, "%s,", buff); +} + +static void +stmwpp_waypt_cb(const waypoint *wpt) +{ + char cdate[16], ctime[16]; + struct tm tm; + + if (track_index != track_num) return; + + tm = *gmtime(&wpt->creation_time); + tm.tm_year += 1900; + tm.tm_mon++; + + snprintf(cdate, sizeof(cdate), "%02d/%02d/%04d", tm.tm_mon, tm.tm_mday, tm.tm_year); + snprintf(ctime, sizeof(ctime), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec); + + switch(what) + { + case STM_WAYPT: + fprintf(fout, "WP,D,%s,", wpt->shortname); + break; + + case STM_TRKPT: + fprintf(fout, "TP,D,"); + break; + } + stmwpp_write_double(wpt->latitude); + stmwpp_write_double(wpt->longitude); + fprintf(fout, "%s,%s", cdate, ctime); + switch(what) + { + case STM_WAYPT: + fprintf(fout, ".%02d", wpt->centiseconds); + break; + case STM_TRKPT: + fprintf(fout, ".%03d", wpt->centiseconds * 10); + break; + } + fprintf(fout, ",\r\n"); +} + +static void +stmwpp_data_write(void) +{ + track_num = 0; + if (index_opt != NULL) + track_index = atoi(index_opt); + else + track_index = 1; + + fprintf(fout, "Datum,WGS 84,WGS 84,0,0,0,0,0\r\n"); + + switch(global_opts.objective) + { + case wptdata: + what = STM_WAYPT; + track_index = track_num; + waypt_disp_all(stmwpp_waypt_cb); + break; + case rtedata: + what = STM_WAYPT; + track_disp_all(stmwpp_track_hdr, stmwpp_track_tlr, stmwpp_waypt_cb); + break; + case trkdata: + what = STM_TRKPT; + track_disp_all(stmwpp_track_hdr, stmwpp_track_tlr, stmwpp_waypt_cb); + break; + } +} + +ff_vecs_t stmwpp_vecs = { + ff_type_file, + FF_CAP_RW_ALL, + stmwpp_rd_init, + stmwpp_rw_init, + stmwpp_rd_deinit, + stmwpp_rw_deinit, + stmwpp_data_read, + stmwpp_data_write, + NULL, + stmwpp_args, + CET_CHARSET_MS_ANSI, 0 +}; diff --git a/gpsbabel/testo b/gpsbabel/testo index c5f5248a8..4cc088d35 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -842,4 +842,15 @@ ${PNAME} -i ignrando -f reference/track/ignrando-sample.rdn -o ignrando -F ${TMP ${PNAME} -i ignrando -f ${TMPDIR}/ignrando-sample.rdn -o gpx -F ${TMPDIR}/ignrando-sample.gpx compare ${TMPDIR}/ignrando-sample.gpx reference/track/ignrando-sample.gpx +# +# STMwpp "Suunto Track Manager" WaypointPlus format tests +# +rm -f ${TMPDIR}/stmwpp-* +${PNAME} -i stmwpp -f reference/track/stmwpp-track.txt -o gpx -F ${TMPDIR}/stmwpp-track.gpx +compare ${TMPDIR}/stmwpp-track.gpx reference/track/stmwpp-track.gpx +${PNAME} -i stmwpp -f reference/route/stmwpp-route.txt -o gpx -F ${TMPDIR}/stmwpp-route.gpx +compare ${TMPDIR}/stmwpp-route.gpx reference/route/stmwpp-route.gpx +${PNAME} -i stmwpp -f reference/route/stmwpp-route.txt -o stmwpp -F ${TMPDIR}/stmwpp-route.txt +compare ${TMPDIR}/stmwpp-route.txt reference/route/stmwpp-route.txt + exit 0 diff --git a/gpsbabel/vecs.c b/gpsbabel/vecs.c index cd8a195d6..9fb4d0c01 100644 --- a/gpsbabel/vecs.c +++ b/gpsbabel/vecs.c @@ -87,6 +87,7 @@ extern ff_vecs_t gdb_vecs; extern ff_vecs_t bcr_vecs; extern ff_vecs_t coto_vecs; extern ff_vecs_t ignr_vecs; +extern ff_vecs_t stmwpp_vecs; static vecs_t vec_list[] = { @@ -434,7 +435,13 @@ vecs_t vec_list[] = { "ignrando", "IGN Rando track files", "rdn" - }, + }, + { + &stmwpp_vecs, + "stmwpp", + "Suunto Track Manager (STM) WaypointPlus files", + "txt" + }, { NULL, NULL, -- 2.30.2